package common.activiti.web.action;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.activiti.engine.FormService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.form.FormProperty;
import org.activiti.engine.form.StartFormData;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import common.rbac.po.Group;
import common.security.service.UserService;
import common.security.web.util.SecurityUtil;
import common.web.vo.Result;

/**
 * 流程定义相关功能：读取动态表单字段、读取外置表单内容
 *
 */
@Controller
@RequestMapping(value = "/bpm/process")
public class ProcessDefinitionController {

    private Logger logger = Logger.getLogger(getClass());

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private FormService formService;

    @Autowired
    private IdentityService identityService;
    
    @Autowired
    @Qualifier("userServiceImpl")
    private UserService userService;

    /**
     * 读取启动流程的表单字段
     */
    @RequestMapping(value = "getform/start")
    @ResponseBody
    public Result readStartForm(@RequestBody JSONObject json) throws Exception {
    	String processDefinitionId = json.getString("processDefinitionId");
    	if(StringUtils.isBlank(processDefinitionId)){
    		return Result.fail("流程定义ID不能为空！");
    	}
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(processDefinitionId).singleResult();

        String userId = SecurityUtil.getUserName();
        Set<Group> groupList = userService.getGroups(userId);

        // 权限拦截
        boolean startable = false;
        List<IdentityLink> identityLinks = repositoryService.getIdentityLinksForProcessDefinition(processDefinition.getId());
        if (identityLinks == null || identityLinks.isEmpty()) {
            startable = true;
        } else {
            for (IdentityLink identityLink : identityLinks) {
                if (StringUtils.isNotBlank(identityLink.getUserId()) && identityLink.getUserId().equals(userId)) {
                    startable = true;
                    break;
                }

                if (StringUtils.isNotBlank(identityLink.getGroupId())) {
                    for (Group group : groupList) {
                        if (group.getName().equals(identityLink.getGroupId())) {
                            startable = true;
                            break;
                        }
                    }
                }
            }
        }

        if (!startable) {
        	return Result.fail("您无权启动【" + processDefinition.getName() + "】流程！");
        }

        boolean hasStartFormKey = processDefinition.hasStartFormKey();
        Map<Object, Object> reMap = new HashMap<Object, Object>();

        Result result = Result.createResult(null);
        boolean hasUsers = false;
        // 根据是否有formkey属性判断使用哪个展示层
        // 判断是否有formkey属性
        if (hasStartFormKey) {
            Object renderedStartForm = formService.getRenderedStartForm(processDefinitionId);
            result.addMap("startFormData", renderedStartForm);
            result.addMap("processDefinition", processDefinition);
        } else { // 动态表单字段
            StartFormData startFormData = formService.getStartFormData(processDefinitionId);
            if(null != startFormData) {
            	List<FormProperty> formProperties = startFormData.getFormProperties();
            	for (FormProperty fp : formProperties) {
            		Map<String, Object> infoMap = new HashMap<String, Object>();
            		reMap.put(fp.getId(), infoMap);
            		String[] keys = {"datePattern", "values"};
            		if("users".equals(fp.getType().getName())) {
            			hasUsers = true;
            		}
            		for (String key : keys) {
            			Object information = fp.getType().getInformation(key);
            			infoMap.put(key, information);
					}
				}
            }
            result.addMap("formPropertiesInformation", reMap);
            result.addMap("startFormData", startFormData);
        }
        if(hasUsers) {
        	result.addMap("hasUsers", hasUsers);
        }
        result.addMap("hasStartFormKey", hasStartFormKey);
        result.addMap("processDefinitionId", processDefinitionId);
        return result;
    }

    @RequestMapping(value = "process_instance/start")
    @ResponseBody
    public Result startProcessInstance(@RequestBody JSONObject json) {
    	String pdid = json.getString("processDefinitionId");
    	JSONObject fromValues = json.getJSONObject("formData");
    	if(StringUtils.isBlank(pdid)){
    		return Result.fail("流程定义ID不能为空！");
    	}
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(pdid).singleResult();
        boolean hasStartFormKey = processDefinition.hasStartFormKey();

        Map<String, String> formValues = new HashMap<String, String>();

        if (hasStartFormKey) { // formkey表单
            Set<Map.Entry<String, Object>> entrySet = fromValues.entrySet();
            for (Entry<String, Object> entry : entrySet) {
                String key = entry.getKey();
                String v = null;
                Object value = fromValues.get(key);
                if(value instanceof JSONArray) {
            		v = StringUtils.join(value, ",");
            	} else if(null != value) {
            		v = value.toString();
            	}
                formValues.put(key, v);
            }
        } else { // 动态表单
            // 先读取表单字段在根据表单字段的ID读取请求参数值
            StartFormData formData = formService.getStartFormData(pdid);

            // 从请求中获取表单字段的值
            List<FormProperty> formProperties = formData.getFormProperties();
            for (FormProperty formProperty : formProperties) {
            	if (!"javascript".equals(formProperty.getType().getName())) {
					String v = null;
					Object value = fromValues.get(formProperty.getId());
					if (value instanceof JSONArray) {
						v = StringUtils.join(((JSONArray) value).iterator(), ",");
					} else if(null != value) {
						v = value.toString();
					}
					formValues.put(formProperty.getId(), v);
				}
            
            }
        }

        // 获取当前登录的用户
        String userId = SecurityUtil.getUserName();
        identityService.setAuthenticatedUserId(userId);

        // 提交表单字段并启动一个新的流程实例
        ProcessInstance processInstance = formService.submitStartFormData(pdid, formValues);
        logger.debug(MessageFormat.format("start a processinstance: {0}", processInstance.getId()));
        return new Result(true, "流程已启动，实例ID：" + processInstance.getId());
    }

}
